package com.hmy.infrastructure.service.map.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.hmy.ccp.error.exception.HMYRuntimeException;
import com.hmy.infrastructure.bo.request.map.DistrictCityQueryRequest;
import com.hmy.infrastructure.bo.request.map.DistrictQueryRequest;
import com.hmy.infrastructure.bo.request.map.TruckRoutePlanRequest;
import com.hmy.infrastructure.bo.response.map.DistrictCityResponse;
import com.hmy.infrastructure.bo.response.map.DistrictInfoResponse;
import com.hmy.infrastructure.bo.response.map.DistrictQueryResponse;
import com.hmy.infrastructure.bo.response.map.TruckRoutePlanResponse;
import com.hmy.infrastructure.common.constant.RedisKeyConstant;
import com.hmy.infrastructure.service.map.IMapService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author seven.qi 齐胜南
 * @version 1.0
 * @description 高德地图Service实现
 * @date 2024/4/16 11:06
 */
@Service
@Data
@Slf4j
public class MapServiceImpl implements IMapService {

    @Value("${map.districtUrl}")
    private String districtUrl = "https://restapi.amap.com/v3/config/district";

    @Value("${map.truckUrl}")
    private String truckUrl = "https://restapi.amap.com/v4/direction/truck";

    @Value("${map.key}")
    private String key;

    @Value("${map.secretKey}")
    private String secretKey;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public DistrictQueryResponse districtQuery(DistrictQueryRequest request) {
        Map<String, Object> map = BeanUtil.beanToMap(request, false, true);
        map.put("sig", md5(map, key, secretKey));
        log.info("request gaode map params : {}", map);
        String res = HttpUtil.get(districtUrl, map);
        log.info("request gaode map response : {}", res);
        JSONObject jsonObject = JSONUtil.parseObj(res);
        if (jsonObject.getInt("status") != 1) {
            log.error("高德地图查询行政区域失败，错误码：{}, 状态说明：{}, 错误具体原因：{}", jsonObject.getInt("errcode"), jsonObject.getStr("errmsg"), jsonObject.getStr("errdetail"));
            throw new HMYRuntimeException(404000019);
        }
        return JSONUtil.toBean(res, DistrictQueryResponse.class);
    }

    @Override
    public DistrictCityResponse allDistrictCity(DistrictCityQueryRequest request) {
        DistrictCityResponse response = new DistrictCityResponse();
        if (redisTemplate.hasKey(RedisKeyConstant.DISTRICT_CITY_CACHE_KEY)) {
            response.setDistricts(JSONUtil.toList(JSONUtil.toJsonStr(redisTemplate.opsForValue().get(RedisKeyConstant.DISTRICT_CITY_CACHE_KEY)), DistrictInfoResponse.class));
            return response;
        } else {
            DistrictQueryRequest req = new DistrictQueryRequest();
            req.setSubdistrict(2);
            req.setOffset(Integer.MAX_VALUE);
            DistrictQueryResponse resp = districtQuery(req);
            List<DistrictInfoResponse> list = new ArrayList<>();
            getAllCityName(resp.getDistricts(), list);
            response.setDistricts(list);
            redisTemplate.opsForValue().set(RedisKeyConstant.DISTRICT_CITY_CACHE_KEY, JSONUtil.toJsonStr(list), 30L, TimeUnit.DAYS);
            return response;
        }
    }

    @Override
    public TruckRoutePlanResponse truckRoutePlan(TruckRoutePlanRequest request) {
        Map<String, Object> map = BeanUtil.beanToMap(request, false, true);
        map.put("sig", md5(map, key, secretKey));
        log.info("request gaode map params : {}", map);
        String res = HttpUtil.get(truckUrl, map);
        log.info("request gaode map response : {}", res);
        JSONObject jsonObject = JSONUtil.parseObj(res);
        if (jsonObject.getInt("status") != 1) {
            log.error("高德地图查询行政区域失败，错误码：{}, 状态说明：{}, 错误具体原因：{}", jsonObject.getInt("errcode"), jsonObject.getStr("errmsg"), jsonObject.getStr("errdetail"));
            throw new HMYRuntimeException(404000020);
        }
        return JSONUtil.toBean(jsonObject.getStr("data"), TruckRoutePlanResponse.class);
    }

    private void getAllCityName(List<DistrictInfoResponse> response, List<DistrictInfoResponse> list) {
        if (CollUtil.isNotEmpty(response)) {
            response.forEach(districtInfoResponse -> {
                if (districtInfoResponse.getLevel().equals("city")) {
                    list.add(districtInfoResponse);
                }
                getAllCityName(districtInfoResponse.getDistricts(), list);
            });
        }
    }
    private static String md5(Map<String, Object> params, String key, String secretKey) {
        params.put("key", key);
        params.put("timestamp", System.currentTimeMillis());
        StringBuilder sb = new StringBuilder();
        List<String> collect = params.keySet().stream().sorted().collect(Collectors.toList());
        for (String s : collect) {
            String value = params.get(s).toString();
            sb.append(s).append("=").append(value).append("&");
        }
        String result = sb.substring(0, sb.length() - 1) + secretKey;
        return DigestUtil.md5Hex(result, StandardCharsets.UTF_8);
    }}
